package com.srtp.secureprotocol.cipherstream;

import com.srtp.secureprotocol.util.Util;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 内容长度限制输入流
 * <p>
 * 继承自FilterInputStream，用于读取指定长度（contentLength）的数据流。
 * 当读取的字节数达到指定长度后，后续读取将返回EOF（-1）。
 * 主要用于处理网络协议中固定长度的数据块（如HTTP Content-Length）。
 */
public class ContentLengthInputStream extends FilterInputStream {

    // 剩余可读取字节数
    private long bytesRemaining;

    /**
     * 构造函数
     *
     * @param inputStream  底层输入流
     * @param contentLength 限制读取的最大字节数
     */
    public ContentLengthInputStream(InputStream inputStream, long contentLength) {
        super(inputStream);
        this.bytesRemaining = contentLength;
    }

    /**
     * 读取单个字节
     *
     * @return 读取的字节（0-255），如果已达长度限制则返回-1
     * @throws IOException 如果发生I/O错误
     */
    @Override
    public int read() throws IOException {
        // 检查是否已达长度限制
        if (bytesRemaining == 0) return -1;

        // 从底层流读取字节
        int result = super.read();
        // 成功读取后减少剩余计数（即使读到EOF也递减，但此处通常预期有数据）
        bytesRemaining--;

        return result;
    }

    /**
     * 读取字节数组（等效于read(buffer, 0, buffer.length)）
     *
     * @param buffer 目标缓冲区
     * @return 实际读取的字节数，如果已达长度限制则返回-1
     * @throws IOException 如果发生I/O错误
     */
    @Override
    public int read(byte[] buffer) throws IOException {
        return read(buffer, 0, buffer.length);
    }

    /**
     * 读取字节数组的指定区间
     *
     * @param buffer 目标缓冲区
     * @param offset 存储起始偏移量
     * @param length 最大读取长度
     * @return 实际读取的字节数，如果已达长度限制则返回-1
     * @throws IOException 如果发生I/O错误
     */
    @Override
    public int read(byte[] buffer, int offset, int length) throws IOException {
        // 检查是否已达长度限制
        if (bytesRemaining == 0) return -1;

        // 计算本次允许读取的最大长度（取剩余长度和请求长度的最小值）
        int maxToRead = (int) Math.min(length, bytesRemaining);
        // 从底层流读取数据
        int result = super.read(buffer, offset, maxToRead);

        // 如果读取成功（result > 0），更新剩余字节数
        if (result > 0) {
            bytesRemaining -= result;
        }
        return result;
    }

}